package com.waijiaojun.tpo.crawler;

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.waijiaojun.tpo.entity.Question;
import com.waijiaojun.tpo.entity.Scenario;
import com.waijiaojun.tpo.entity.Vocabulary;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Peter on 2018/2/6.
 */

public class CrawlerXiaozhanTpo {
    /**
     * 入口函数
     *
     * @param args
     * @throws ParseException
     */
    public static void main(String[] args) throws ParseException, IOException {
        List<TpoXzDto> urlList = new ArrayList<>();
        TpoXzDto dto = new TpoXzDto("TPO53.5", "http://top.zhan.com/toefl/listen/review-1319-13-112047.html");
        prepareHtml(dto);
    }

    private static void prepareHtml(TpoXzDto dto) throws IOException {
        try (final WebClient webClient = new WebClient()) {
//            final HtmlPage page = webClient.getPage("http://top.zhan.com/toefl/listen/review-1282-13.html"); // 排序题
            final HtmlPage page = webClient.getPage(dto.getUrl()); // 表格题

            // 等待页面执行Javascript。页面的重点词汇通过调用Ajax获取的，然后渲染到页面上
            int wait = 0;
            int nbProcess = 1;
            while (nbProcess > 0 && wait < 10) {
                nbProcess = webClient.waitForBackgroundJavaScript(1000);
                if (wait == 9) {
                    System.err.println("** needs more time ** ");
                }
                wait++;
                System.out.println("wait:" + wait + "    nbProcess:" + nbProcess);
            }
            final String pageAsXml = page.asXml();
            System.out.println(pageAsXml);
//            final String pageAsText = page.asText();
            paresTpoPage(pageAsXml, dto);
        }
    }


    private static void paresTpoPage(String html, TpoXzDto dto) throws IOException {

    //  Scenario scenario = scenarioDao.findByTpoName(dto.getTpoName());
        Scenario scenario = new Scenario();// 场景
        List<Vocabulary> vocabularyList = new ArrayList<>();// 词汇
        List<Question> questionList = new ArrayList<>();// 问题

        //解析Url获取Document对象
//        Document document = Jsoup.connect(url).get();
        Document document = Jsoup.parse(html);
        //获取网页源码文本内容
        String doc = document.toString();
        // 按指定模式在字符串查找
        String pattern = "https://tikustorage.oss-cn-hangzhou.aliyuncs.com/TPO_Audio/tpo[\"\\w:/ \\.-]+mp3";

        // 创建 Pattern 对象
        Pattern r = Pattern.compile(pattern);

        // 现在创建 matcher 对象
        Matcher m = r.matcher(doc);
        if (m.find()) {
            String autio_url = m.group(0);
            scenario.setAudioUrl(autio_url.trim());
            System.out.println("MATCH audio_url:" + autio_url);
        } else {
            System.out.println("NO MATCH");
        }
//            System.out.println(document.toString());

        // TOP Name
        Elements topElem = document.select(".main_title_review");
        String tpoName_titme = topElem.text();
        String[] strs = tpoName_titme.split(" ");
        String tpoName = strs[0];
        String nameCn = strs[1];
        scenario.setTpo_name(tpoName);
        scenario.setNameCn(nameCn);
        System.out.println("TPO Name:" + tpoName);
        System.out.println("Article Title Cn:" + nameCn);

        Elements nameEnElem = document.select(".sub_title_review");
        String nameEn = nameEnElem.text();
        scenario.setNameEn(nameEn);
        System.out.println("Article Title En:" + nameEn);

        Elements article = document.getElementsByClass("article");
        // 英文
        Elements articleEnList = article.select("span .text");
        StringBuffer articleEnBuf = new StringBuffer("");
        for (int i = 0; i < articleEnList.size(); i++) {
            String en = articleEnList.get(i).text();
            articleEnBuf.append(en.trim());
            System.out.println(i + ". " + en.trim());
        }
        scenario.setArticleEn(articleEnBuf.toString());

        // 中文
        Elements articleCnList = article.select("span[data-translation]");
        StringBuffer articleCnBuf = new StringBuffer("");
        for (int i = 0; i < articleCnList.size(); i++) {
            String cn = articleCnList.get(i).attr("data-translation");
            articleCnBuf.append(cn.trim());
            System.out.println(i + ". " + cn.trim());
        }
        scenario.setArticleCn(articleCnBuf.toString());

        // 词汇 .toefl_listen_review_left_content .article .underline
        Elements vocabularys = document.select(".toefl_listen_review_left_content .article .underline");
        System.out.println("词汇:");
        for (int i = 0; i < vocabularys.size(); i++) {
            String vocabulary = vocabularys.get(i).text();
            Vocabulary v = new Vocabulary();
            v.setWord(vocabulary);
            vocabularyList.add(v);
            System.out.println(vocabulary);
        }

        printQuestion(1L, document, questionList);


        // 其他问题对应的连接
        Elements as = document.getElementById("footer_review").getElementsByTag("a");
        for (int i = 1; i < as.size(); i++) {
            String question_href = as.get(i).attr("href");
            // System.out.println(i + ". " +question_href);
            Document document_q = Jsoup.connect("http://top.zhan.com" + question_href).get();
            printQuestion(i + 1L, document_q, questionList);
        }
    }

    private static void printQuestion(Long number, Document document, List<Question> questionList) {
        Question questionObj = new Question();
        questionList.add(questionObj);
        Long type = null;
        // 问题
        Elements question = document.select("div .question");

        // 题干
        String questionContent = question.select("div .q_tit").select("div[class='left text']").text();
        System.out.println("Question " + number + " : " + questionContent);
        questionObj.setContent_en(questionContent);
        questionObj.setNumber(number);

        // 选项
        StringBuffer optionsSb = new StringBuffer("[");
        Elements table = question.select("table");
        Elements sort = question.select(" .dragsec");
        // 表格题 选项
        if (table.size() > 0) {
            optionsSb.append("{");
            StringBuffer columns = new StringBuffer("\"columns\": [");
            StringBuffer rows = new StringBuffer("\"rows\": [");
            Elements trs = table.select("tr");
            for (int i = 0; i < trs.size(); i++) {
                if (i == 0) {
                    // 第一行提取列头
                    Elements tds = trs.get(i).select("td");
                    for (int j = 0; j < tds.size(); j++) {
                        if (j != 0) {
                            String columnHead = tds.get(j).text();
                            System.out.println("column " + j + ". " + columnHead);
                            columns.append("{\"id\": " + j + ",\"value\": \"" + columnHead + "\"}");
                            if (j != tds.size() - 1) {
                                columns.append(",");
                            }
                        }
                    }
                    columns.append("]");
                } else {
                    // 提取行头
                    Elements tds = trs.get(i).select("td");
                    for (int j = 0; j < tds.size(); j++) {
                        if (j == 0) {
                            String rowHead = tds.get(j).text();
                            System.out.println("row " + i + ". " + rowHead);
                            rows.append("{\"id\": " + i + ",\"value\": \"" + rowHead + "\"}");
                            if (i != trs.size() - 1) {
                                rows.append(",");
                            }
                        }
                    }
                }

            }
            rows.append("]");
            type = 4L;
            optionsSb.append(rows).append(",").append(columns);
            optionsSb.append("}]");
        } else if (sort.size() > 0) {
            // 排序题选项
            for (int i = 0; i < sort.size(); i++) {
                String option = sort.get(i).text();
                String label = option.substring(0, 1);
                String opt_cont = option.substring(2).trim();
                System.out.println(label + "  " + opt_cont);
                optionsSb.append("{\"id\": " + (i + 1) + ", \"rows\": [],\"columns\": [],\"label\": \"" + label + "\",\"content\": \"" + opt_cont + "\"}");
                if (i != sort.size() - 1) {
                    optionsSb.append(",");
                }
            }
            type = 3L;
            optionsSb.append("]");
        } else {
            //  单选、多选选项
            Elements ops = document.select(".question_option .ops > label");
            for (int i = 0; i < ops.size(); i++) {
                String option = ops.get(i).text();
                String label = option.substring(0, 1);
                String opt_cont = option.substring(2).trim();
                System.out.println(label + "  " + opt_cont);
                optionsSb.append("{\"id\": " + (i + 1) + ", \"rows\": [],\"columns\": [],\"label\": \"" + label + "\",\"content\": \"" + opt_cont + "\"}");
                if (i != ops.size() - 1) {
                    optionsSb.append(",");
                }
            }
            optionsSb.append("]");
        }
        String options = optionsSb.toString();
        questionObj.setOption(options);
        System.out.println(" options:" + options);

        Elements questionAnswerEle = question.select("div .correctAnswer > span");
        // 答案
        String answer = questionAnswerEle.get(0).text();
        System.out.println("  answer:" + answer);
        // 根据答案数量判断题型
        if (type == null) {
            if (answer.length() == 1) {
                type = 1L;
            } else {
                type = 2L;
            }
        }
        questionObj.setType(type);
        System.out.println("  question Type: " + type);

        StringBuffer answerJson = new StringBuffer("[");

        String[] anstr = answer.split("");
        if (type.intValue() != 4) {
            for (int i = 0; i < anstr.length; i++) {

                answerJson.append(toId(anstr[i]));
                if (i != anstr.length - 1) {
                    answerJson.append(",");
                }
            }
        } else {
            // 组装表格题的json格式答案
            for (int i = 0; i < anstr.length; i++) {
                answerJson.append("{\"id\": " + i + ",\"result\": [" + toId(anstr[i]) + "]}");
                if (i != anstr.length - 1) {
                    answerJson.append(",");
                }
            }
        }

        answerJson.append("]");
        questionObj.setAnswer(answerJson.toString());
        System.out.println("  question_answer: " + questionObj.getAnswer());

        // 是否带有音频
        Elements isAudio = question.select("div div.audio_content");
        if (isAudio.size() > 0) {
            System.out.println("  have audio: true");
            questionObj.setAudio_url("true");
        }

        // 题目解析
        Elements resolve = question.select("div.resolve_content");
        if (resolve.size() > 0) {
            String resolve_content = resolve.text();
            System.out.println("  " + resolve_content);
            questionObj.setAnalysis(resolve_content);
        } else {
            System.out.println("  无题目解析");
        }

        System.out.println();

    }

    private static int toId(String str) {
        if (str.contains("A")) {
            return 1;
        } else if (str.contains("B")) {
            return 2;
        } else if (str.contains("C")) {
            return 3;
        } else if (str.contains("D")) {
            return 4;
        } else if (str.contains("E")) {
            return 5;
        } else if (str.contains("F")) {
            return 6;
        } else if (str.contains("G")) {
            return 7;
        } else if (str.contains("H")) {
            return 8;
        } else {
            throw new RuntimeException("无效的答案：" + str);
        }
    }

}
